package com.sudoku.screen;

import java.util.ArrayList;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.sudoku.Sudoku;
import com.sudoku.background.BackgroundManager;
import com.sudoku.observer.Event;
import com.sudoku.observer.Subject;
import com.sudoku.sound.AudioManager;
import com.sudoku.utility.Constants;
import com.sudoku.utility.Locator;

public class MenuScreen implements Screen, Constants {
	private BitmapFont textFont, titleFont, backgroundFont;
	private Stage stage;
	private TextButton buttonExit, buttonEasy, buttonHard, buttonExtreme, buttonContinue, buttonOptions;
	private Label heading;
	private Skin skin;
	private TextureAtlas atlas;
	private TextButtonStyle textButtonStyle, playStyle, exitStyle;
	private final ArrayList<TransitionEffect> effects;
	private SpriteBatch uiBatch;
	private Sudoku game;
	private final Subject subject;
	private BackgroundManager backgroundManager;

	public static float BUTTON_PLAY_HEIGHT = 0.55F;
	public static float HEADING_HEIGHT = 0.80F;
	public static float SERVICES_HEIGHT = 0.12F;

	public MenuScreen(final Sudoku game, AudioManager aud, final Subject sub, Camera camera) {
		this.game = game;
		this.subject = sub;
		backgroundManager = new BackgroundManager();
		stage = new Stage();
		stage.setViewport(Locator.getViewport());
		uiBatch = new SpriteBatch();

		FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal(FONT));
		FreeTypeFontParameter param = new FreeTypeFontParameter();
		param.size = (int) (96);
		titleFont = generator.generateFont(param);

		param.size = (int) (80);
		textFont = generator.generateFont(param);

		param.size = (int) (40);
		backgroundFont = generator.generateFont(param);
		backgroundFont.setColor(new Color(0f, 0f, 0f, 0.3f));
		generator.dispose();

		atlas = new TextureAtlas(Gdx.files.internal("data/button.pack"));
		skin = new Skin(atlas);

		textButtonStyle = new TextButtonStyle();
		textButtonStyle.up = skin.getDrawable("button.up");
		textButtonStyle.down = skin.getDrawable("button.down");
		textButtonStyle.pressedOffsetX = 1;
		textButtonStyle.pressedOffsetY = -1;
		textButtonStyle.font = textFont;
		playStyle = new TextButtonStyle(textButtonStyle);
		playStyle.fontColor = new Color(0.5F, 0.5F, 0.5F, 1f);
		exitStyle = new TextButtonStyle(textButtonStyle);
		exitStyle.fontColor = new Color(0.5F, 0.5F, 0.5F, 1f);

		// create a transition screen
		effects = new ArrayList<TransitionEffect>();
		effects.add(new FadeOutTransitionEffect(0.5f));
		effects.add(new FadeInTransitionEffect(0.8f));

		createButtons();

		// create title
		LabelStyle headingStyle = new LabelStyle(titleFont, new Color(0.5F, 0.5F, 0.5F, 1f));
		heading = new Label("Sudoku", headingStyle);

		heading.setPosition(ACTUAL_VIRTUAL_WIDTH * 0.1f, ACTUAL_VIRTUAL_HEIGHT * HEADING_HEIGHT);

		buttonEasy.setPosition(ACTUAL_VIRTUAL_WIDTH * 0.1f, ACTUAL_VIRTUAL_HEIGHT * (HEADING_HEIGHT-0.16f));
		buttonHard.setPosition(ACTUAL_VIRTUAL_WIDTH * 0.1f, ACTUAL_VIRTUAL_HEIGHT * (HEADING_HEIGHT-0.32f));
		buttonExtreme.setPosition(ACTUAL_VIRTUAL_WIDTH * 0.1f, ACTUAL_VIRTUAL_HEIGHT * (HEADING_HEIGHT-0.48f));
		buttonExit.setPosition(ACTUAL_VIRTUAL_WIDTH * 0.1f, ACTUAL_VIRTUAL_HEIGHT * (HEADING_HEIGHT - 0.7F));
		buttonContinue.setPosition(ACTUAL_VIRTUAL_WIDTH * 0.5f, ACTUAL_VIRTUAL_HEIGHT * (HEADING_HEIGHT - 0.16F));
		buttonOptions.setPosition(ACTUAL_VIRTUAL_WIDTH * 0.5f, ACTUAL_VIRTUAL_HEIGHT * (HEADING_HEIGHT- 0.48F));
		
		stage.addActor(buttonEasy);
		stage.addActor(buttonHard);
		stage.addActor(buttonExtreme);
		stage.addActor(buttonContinue);
		stage.addActor(buttonOptions);
		hideContinueButton();

		stage.addActor(buttonExit);
		stage.addActor(heading);

		subject.notify(Event.EVENT_START_MENU);

		uiBatch.setTransformMatrix(stage.getCamera().view);
		uiBatch.setProjectionMatrix(stage.getCamera().projection);
	}


	private void hideContinueButton() {
		if(Locator.gameInProgress){
			buttonContinue.setVisible(true);
			buttonContinue.setDisabled(false);
		} else {
			buttonContinue.setVisible(false);
			buttonContinue.setDisabled(true);
		}
		
	}

	protected void startGame() {
		PuzzleLoadingScreen next = game.getPuzzleLoadingScreen();
		next.setBackground(backgroundManager);
		game.setScreen(next);
		subject.notify(Event.EVENT_SHOW_LOAD_SCREEN);
	}
	
	public void gotoGameScreen(){
		GameScreen next = game.getGameScreen();
		next.show();
		game.setScreen(next);
	}
	
	protected void gotoOptionsScreen() {
		OptionsScreen next = game.getOptionsScreen();
		next.show();
		game.setScreen(next);
		
	}


	@Override
	public void render(float delta) {
		Gdx.gl.glClearColor(1.0f, 1.0f, 1.0f, 1);
		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
		uiBatch.begin();
		backgroundManager.render(uiBatch, backgroundFont);
		uiBatch.end();

		backgroundManager.update(delta);
		stage.act(delta);
		stage.draw();

	}

	@Override
	public void resize(int width, int height) {
		stage.getViewport().update(width, height, true);
	}

	@Override
	public void show() {
		effects.clear();
		effects.add(new FadeOutTransitionEffect(0.5f));
		effects.add(new FadeInTransitionEffect(0.5f));
		hideContinueButton();
		Gdx.input.setInputProcessor(stage);
	}

	@Override
	public void hide() {
		Gdx.input.setInputProcessor(null);
	}

	private void createButtons() {
		// create buttons
		buttonEasy = new TextButton("Easy", playStyle);
		buttonEasy.addListener(new ClickListener() {
			@Override
			public void clicked(InputEvent event, float x, float y) {
				subject.notify(Event.EVENT_CLICK);
				Locator.setDifficulty(DIFFICULTY.EASY);
				startGame();
			}
		});
		buttonEasy.pad(10.0f);
		
		buttonHard = new TextButton("Hard", exitStyle);
		buttonHard.addListener(new ClickListener() {
			@Override
			public void clicked(InputEvent event, float x, float y) {
				subject.notify(Event.EVENT_CLICK);
				Locator.setDifficulty(DIFFICULTY.HARD);
				startGame();
			}
		});
		buttonHard.pad(10.0f);
		
		buttonExtreme = new TextButton("Extreme", exitStyle);
		buttonExtreme.addListener(new ClickListener() {
			@Override
			public void clicked(InputEvent event, float x, float y) {
				subject.notify(Event.EVENT_CLICK);
				Locator.setDifficulty(DIFFICULTY.EXTREME);
				startGame();
			}
		});
		buttonExtreme.pad(10.0f);

		buttonExit = new TextButton("Exit", exitStyle);
		buttonExit.addListener(new ClickListener() {
			@Override
			public void clicked(InputEvent event, float x, float y) {
				subject.notify(Event.EVENT_CLICK);
				Locator.writeSave();
				Gdx.app.exit();
			}
		});
		buttonExit.pad(10.0f);
		
		buttonContinue = new TextButton("Continue Game", exitStyle);
		buttonContinue.addListener(new ClickListener() {
			@Override
			public void clicked(InputEvent event, float x, float y) {
				subject.notify(Event.EVENT_CONTINUE);
				if (Locator.adTimer >= Locator.MAX_AD_TIME) {
					Locator.getDevice().displayInterstitial();
					Locator.resetAdTimer();
					subject.notify(Event.EVENT_CLICK);
				}
				gotoGameScreen();
			}
		});
		buttonContinue.pad(10.0f);
		
		buttonOptions = new TextButton("Options", exitStyle);
		buttonOptions.addListener(new ClickListener() {
			@Override
			public void clicked(InputEvent event, float x, float y) {
				gotoOptionsScreen();
				subject.notify(Event.EVENT_CLICK);
			}
		});
		buttonOptions.pad(10.0f);

	}

	@Override
	public void pause() {
	}

	@Override
	public void resume() {
	}

	@Override
	public void dispose() {
		stage.dispose();
		atlas.dispose();
		skin.dispose();
	}


	public BackgroundManager getBackground() {
		return backgroundManager;
	}

}